//
// Created by gushen610140 on 2024/3/22.
//

#ifndef DATASTRUCTURECOURSE_GSTATICQUEUE_H
#define DATASTRUCTURECOURSE_GSTATICQUEUE_H

#include <stdexcept>

template<typename T>
class [[maybe_unused]] GStaticQueue {
private:
    T *_data;
    int _head;
    int _tail;
    int _size;

    const int expand_size = 100;
    const int max_size = 1000000;

    void expand() {
        T *newData = (T *) std::realloc(_data, sizeof(T) * (_size + expand_size));
        _head = 0, _size = _size + expand_size;
        delete[] _data;
        _data = newData;
    }

public:
    GStaticQueue() : _data(new T[max_size]), _head(0), _tail(0), _size(max_size) {}

    [[maybe_unused]] void push_back(T value) {
        if ((_tail + 1) % _size == _head) expand();
        _data[_tail] = value;
        _tail = (_tail + 1) % _size;
    }

    [[maybe_unused]] T pop_front() {
        if (_head == _tail) {
            throw std::out_of_range("Index out of range");
        }
        T res = _data[_head];
        _head = (_head + 1) % _size;
        return res;
    }

    [[maybe_unused]] T get_front() {
        if (_head == _tail) {
            throw std::out_of_range("Index out of range");
        }
        return _data[_head];
    }
};


#endif //DATASTRUCTURECOURSE_GSTATICQUEUE_H
